package com.demo.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.*;

/**
 * http client
 *
 * @author jasper
 */
@Service
public class HttpClientService {
    private static Logger logger = LoggerFactory.getLogger(HttpClientService.class);
    private static final String HTTP_HEADER = "http://";
    /**
     * http client
     */
    private static CloseableHttpClient httpClient;

    /**
     * 使用Pooling connection manager构建http客户端
     */
    @PostConstruct
    public void initHttpClient() {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(200);
        cm.setDefaultMaxPerRoute(cm.getMaxTotal());
        cm.setValidateAfterInactivity(10000);

        httpClient = HttpClients.custom()
                .setConnectionManager(cm)
                // 避免 Connection pool shut down httpclient
                .setConnectionManagerShared(true)
                .build();
        logger.info("http client create success");
    }

    /**
     * 关闭http client
     */
    @PreDestroy
    public void closeHttpClient() {
        try {
            if (httpClient != null) {
                httpClient.close();
            }
        } catch (IOException e) {
            logger.error("close http client failed {}", e);
        }
    }

    /**
     * post 请求
     *
     * @param entity HTTP entity
     * @param url    request url
     * @return
     */
    public JSONObject postRequest(HttpEntity entity, String url) {
        RequestConfig requestConfig = RequestConfig.custom()
                // 设置获取连接超时时间
                .setConnectionRequestTimeout(5000)
                // 设置连接上服务器(握手成功)超时时间
                .setConnectTimeout(5000)
                // 设置服务器返回数据(response)超时时间
                .setSocketTimeout(5000)
                .build();
        HttpPost httpPost = new HttpPost("http://" + url);
        httpPost.setConfig(requestConfig);
        httpPost.setEntity(entity);
        boolean isSuccess = false;
        String rs = null;
        try {
            CloseableHttpResponse response = null;
            try {
                response = httpClient.execute(httpPost);
                StatusLine statusLine = response.getStatusLine();
                int statusCode = statusLine.getStatusCode();
                isSuccess = (statusCode == HttpStatus.SC_OK);

                if (!isSuccess) {
                    logger.error("http request failed response code is {} the request url is {}", statusCode, url);
                } else {
                    // 需要释放 InputStream 等不然http pool 不会被释放 复用
                    try (InputStream content = response.getEntity().getContent();
                         BufferedReader reader = new BufferedReader(new InputStreamReader(content))) {
                        String line = "";
                        StringBuilder stringBuilder = new StringBuilder();
                        while ((line = reader.readLine()) != null) {
                            stringBuilder.append(line);
                        }
                        rs = stringBuilder.toString();
                    }
                }
            } catch (IOException e) {
                logger.error("http request url {} error: {}", url, e);
                isSuccess = false;
            } finally {
                if (response != null) {
                    // 该行非常重要否则http client将不会再重用连接，保证entity被消费完
                    EntityUtils.consume(response.getEntity());
                    response.close();
                }
            }
        } catch (Exception e) {
            logger.error("postRequest error: {}", e);
            isSuccess = false;
        }
        return JSON.parseObject(rs);
    }

    /**
     * 封装request的消息为StringEntity
     *
     * @param result StringEntity
     * @return
     */
    public StringEntity getStringEntity(Object result) {
        String jsonString = JSON.toJSONString(result);
        return new StringEntity(jsonString, ContentType.APPLICATION_JSON);
    }
}